package com.zby.simulationHibernate.query;

import com.zby.simulationHibernate.util.common.CommonUtil;
import com.zby.simulationHibernate.util.exception.GenericException;
import com.zby.simulationHibernate.util.factory.SessionClose;
import com.zby.simulationHibernate.util.reflect.PersistentObject;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created By zby on 16:48 2019/1/23
 * 采用类字面常量获取当前对象
 */

public class SqlQuery<T> {


    private ResultTransformer transformer;
    private Map<String, String> aliasMap;
    private Map<Integer, Object> columnParamer;
    private String sql;
    private Connection connection;
    private Class<T> persistenceClass;

    public SqlQuery() {
    }

    public SqlQuery(Connection connection, String sql) {
        this.sql = sql;
        this.connection = connection;
    }

    public SqlQuery(Class<T> persistenceClass, Connection connection, String sql) {
        this(connection, sql);
        this.persistenceClass = persistenceClass;
    }

    /**
     * Created By zby on 19:18 2019/1/27
     * 创建类型
     */
    public SqlQuery addScalar(String tuple, String alias) {
        if (CommonUtil.isNull(aliasMap)) {
            aliasMap = new HashMap<>();
        }
        for (Map.Entry<String, String> entry : aliasMap.entrySet()) {
            String key = entry.getKey();
            if (key.equals(tuple))
                throw new GenericException("alias已经存在，即alias=" + key);
            String value = aliasMap.get(key);
            if (value.equals(alias) && key.equals(tuple))
                throw new GenericException("当前alias的type已经存在，alias=" + key + ",type=" + value);
        }
        aliasMap.put(tuple, alias);
        return this;
    }

    /**
     * Created By zby on 9:20 2019/1/28
     * 数据转换问题
     */
    public SqlQuery setTransformer(ResultTransformer transformer) {
        if (CommonUtil.isNull(aliasMap)) {
            throw new IllegalArgumentException("请添加转换的属性数量");
        }
        transformer.transformTuple(aliasMap);
        this.transformer = transformer;
        return this;
    }

    /**
     * Created By zby on 17:02 2019/1/29
     * 设置查找参数
     */
    public SqlQuery setParamter(int start, Object param) {
        if (CommonUtil.isNull(columnParamer))
            columnParamer = new HashMap<>();
        columnParamer.put(start, param);
        return this;
    }


    /**
     * Created By zby on 23:19 2019/1/23
     * 体检反射的实体类
     */
    public SqlQuery addEntity(Class<T> persistenceClass) {
        this.persistenceClass = persistenceClass;
        return this;
    }


    /**
     * Created By zby on 16:41 2019/1/24
     * 查找值
     */
    public List<T> list() {
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            statement = connection.prepareStatement(sql);
            if (CommonUtil.isNotNull(columnParamer)) {
                for (Map.Entry<Integer, Object> entry : columnParamer.entrySet()) {
                    int key = entry.getKey();
                    Object value = entry.getValue();
                    statement.setObject(key + 1, value);
                }
            }
            resultSet = statement.executeQuery();
            PersistentObject persistentObject = new PersistentObject(persistenceClass, resultSet);
            if (CommonUtil.isNotNull(aliasMap))
                return persistentObject.getPersist(transformer);
            return persistentObject.getPersist();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            SessionClose.closeConnStateResSet(connection, statement, resultSet);
        }
        return null;
    }

    /**
     * Created By zby on 16:41 2019/1/24
     * 查找值
     */
    public T uniqueResult() {
        List<T> list = list();
        if (CommonUtil.isNull(list))
            return null;
        if (list.size() > 1)
            throw new GenericException("本来需要返回一个对象，却返回 " + list.size() + "个对象");
        return list.get(0);
    }

}
